package service

import (
	"errors"
	v1 "server_go/api/v1"
	"server_go/internal/model"
	"server_go/internal/repository"
)

type TagService interface {
	AddTag(req *v1.AddTagRequest) error
	DeleteTag(req *v1.DeleteTagRequest) (*v1.DeleteTagResponse, error)
	UpdateTag(req *v1.UpdateTagRequest) error
	GetAllTag(req *v1.GetTagRequest) (*v1.GetTagResponse, error)
	GetTagById(req *v1.GetTagByIdRequest) (*v1.GetTagByIdResponse, error)
	GetAllTagList() (*v1.GetTagResponse, error)
}

func NewTagService(service *Service,
	tagRepository repository.TagRepository,
	articleRepo repository.ArticleRepository,
) TagService {
	return &tagService{
		Service:       service,
		tagRepository: tagRepository,
		articleRepo:   articleRepo,
	}
}

type tagService struct {
	*Service
	tagRepository repository.TagRepository
	articleRepo   repository.ArticleRepository
}

func (s *tagService) AddTag(req *v1.AddTagRequest) error {
	tag, err := s.tagRepository.GetTagByName(req.Name)
	if err != nil && !errors.Is(err, v1.ErrTagNotExist) {
		return err
	}

	if tag != nil {
		return v1.ErrTagExist
	}

	if err := s.tagRepository.AddTag(&model.Tag{Name: req.Name, Describe: req.Describe}); err != nil {
		return err
	}
	return nil
}

func (s *tagService) DeleteTag(req *v1.DeleteTagRequest) (*v1.DeleteTagResponse, error) {
	if _, err := s.tagRepository.GetTagById(req.TagId); err != nil {
		return nil, err
	}

	// 当前标签存在，那么判定当前标签下有没有文章
	_, count, err := s.articleRepo.GetArticleByTagId(req.TagId, 1, 1)
	if err != nil {
		return nil, nil
	}
	if count > 0 {
		return nil, v1.ErrTagHasArticle
	}

	if err := s.tagRepository.DeleteTag(req.TagId); err != nil {
		return nil, err
	}

	return &v1.DeleteTagResponse{TagId: req.TagId}, nil
}

func (s *tagService) UpdateTag(req *v1.UpdateTagRequest) error {
	// 查询 id 是否存在
	if _, err := s.tagRepository.GetTagById(req.TagId); err != nil {
		return err
	}
	// 查询id名字是否重复

	if _, err := s.tagRepository.GetTagByName(req.TagName); err != nil {
		return err
	}
	tag := &model.Tag{
		Name:     req.TagName,
		Describe: req.Describe,
	}
	if err := s.tagRepository.UpdateTag(req.TagId, tag); err != nil {
		return err
	}
	return nil
}

func (s *tagService) GetAllTag(req *v1.GetTagRequest) (*v1.GetTagResponse, error) {
	tags, total, err := s.tagRepository.GetAllTag(req.Page, req.PageSize)
	if err != nil {
		return nil, err
	}
	resp := ConvertToGetTagResponses(tags) // 数据转换
	return &v1.GetTagResponse{Total: total, Record: resp}, nil
}

func (s *tagService) GetTagById(req *v1.GetTagByIdRequest) (*v1.GetTagByIdResponse, error) {
	resp, err := s.tagRepository.GetTagById(req.TagId)
	if err != nil {
		return nil, err
	}
	return &v1.GetTagByIdResponse{
		TagId:     int64(resp.ID),
		Name:      resp.Name,
		Describe:  resp.Describe,
		CreatedAt: resp.CreatedAt,
		UpdatedAt: resp.UpdatedAt,
		DeletedAt: resp.DeletedAt,
	}, nil
}

func (s *tagService) GetAllTagList() (*v1.GetTagResponse, error) {
	tags, total, err := s.tagRepository.GetAllTagList()
	if err != nil {
		return nil, err
	}
	resp := ConvertToGetTagResponses(tags)
	return &v1.GetTagResponse{Total: total, Record: resp}, nil
}

// ConvertToGetTagResponses 函数功能： 将数据库中的Tag结构体转换为GetTagByIdResponse结构体
// 时间复杂度：O(n)
func ConvertToGetTagResponses(tags []*model.Tag) []v1.GetTagByIdResponse {
	// 返回的结果数组
	resp := make([]v1.GetTagByIdResponse, len(tags))
	// 用for循环进行赋值
	for i, tag := range tags {
		var deletedAt interface{}
		if tag.DeletedAt.Valid {
			deletedAt = tag.DeletedAt.Time
		} else {
			deletedAt = nil
		}

		resp[i] = v1.GetTagByIdResponse{
			TagId:     int64(tag.ID),
			Describe:  tag.Describe,
			Name:      tag.Name,
			CreatedAt: tag.CreatedAt,
			UpdatedAt: tag.UpdatedAt,
			DeletedAt: deletedAt,
		}
	}
	return resp
}
